# coding=utf-8
import pygame, sys  
from pygame.locals import *
import math
import random
import Backpropagation
import Backpropagation2

    
#set up pygame
    
pygame.init() 
  
windowSurface = pygame.display.set_mode((800, 400), 0, 32) 
pygame.display.set_caption("Neural")
img = pygame.image.load("net.ico")
pygame.display.set_icon(img) # 可以填img
  
BLACK = (0, 0, 0) 
WHITE = (255, 255, 255) 
RED = (255, 0, 0) 
GREEN = (0, 255, 0) 
BLUE = (0, 0, 255)
qing= (0,128,128)
yellow=(255,255,0)

BUTTON2=[50,350]
BUTTON1=[350,350]
BUTTON3=[650,350]



def dsp_csr():
    windowSurface.fill(WHITE)
    basicFont = pygame.font.SysFont(None, 48)                          #画反向传输次数
    text = basicFont.render("n=", True, WHITE, BLUE) 
    textRect = text.get_rect() 
    textRect.centerx = 100
    textRect.centery =20 
    windowSurface.blit(text, textRect)
    font = pygame.font.Font("c:\simsun.ttf", 20)          #画按钮
    text = font.render('识别4', True, (0, 0, 255), (0, 255, 0))
    windowSurface.blit(text, BUTTON1)
    font = pygame.font.Font("c:\simsun.ttf", 20)
    text = font.render('识别0', True, (0, 0, 255), (0, 255, 0))
    windowSurface.blit(text, BUTTON2)
    font = pygame.font.Font("c:\simsun.ttf", 20)
    text = font.render('开始学习', True, (0, 0, 255), (0, 255, 0))
    windowSurface.blit(text, BUTTON3)
    return

dsp_csr()

def sigmoid(x: float) -> float:#激活函数
    return 1.0 / (1.0 + math.exp(-x))

def derivative_sigmoid(x: float) -> float:#激活函数反函数
    sig: float = sigmoid(x)
    return sig * (1 - sig)



body_long1=100  #输入层数
body_long2=100   #隐藏层数
body_long3=10    #输出层数
tree_long1=10000   #输入层神经链接数
tree_long2=1000    #隐藏层神经链接数
body1 = [0.1]*body_long1   #输入层
body2  = [0.01]*body_long2  #隐藏层
body3  = [0]*body_long3    #输出层
body3_std  = [0]*body_long3    #输出层标准值

h=0.2  #调整系数
n=35  #反向传输次数

tree1 = [0.01]*tree_long1  #输入层神经链接
tree2 = [0.01]*tree_long2  #隐藏层神经链接

for num in range(0,tree_long1):
    tree1[num]=random.random()/100
for num in range(0,tree_long2):
    tree2[num]=random.random()/50





def disp(n):
 n=n
 font = pygame.font.Font("c:\simsun.ttf", 35)
 text = font.render(str(n) , True, WHITE, BLUE)
 windowSurface.blit(text, (120,0))
 for num1 in range(0,math.floor(body_long1/10)):#画输入层
   for num2 in range(0,10):#画输入层
    if(body1[num1*10+num2]>0.8):
      pygame.draw.circle(windowSurface, RED, (num2*25+100, num1*25+50), 5, 0)
    else:
     pygame.draw.circle(windowSurface, BLUE, (num2*25+100, num1*25+50), 5, 0)

 for num1 in range(0,math.floor(body_long2/10)):#画隐藏层
  for num2 in range(0,10):
      if(body2[num1*10+num2]>0.57):
        pygame.draw.circle(windowSurface, RED, (num2*25+400, num1*25+50), 5, 0)
      else:
        pygame.draw.circle(windowSurface, BLUE, (num2*25+400, num1*25+50), 5, 0)
 for num1 in range(0,math.floor(body_long3/10)):#画输出层
  for num2 in range(0,10):
      if(body3[num1*10+num2]>0.7):
        pygame.draw.circle(windowSurface, RED,(num1*25+700, num2*25+50), 5, 0)
      elif(body3[num1*10+num2]>0.6):
        pygame.draw.circle(windowSurface, yellow,(num1*25+700, num2*25+50), 5, 0) 
      else:
        pygame.draw.circle(windowSurface, BLUE, (num1*25+700, num2*25+50), 5, 0)

 for num1 in range(0,math.floor(body_long3/10)):#画输出层标准值
  for num2 in range(0,10):
      font = pygame.font.Font("c:\simsun.ttf", 15)
      text = font.render(str(num2 ) , True, BLUE, WHITE)
      windowSurface.blit(text, (num1*25+740, num2*25+40) )      
      if(body3_std[num1*10+num2]>0.7):
         pygame.draw.circle(windowSurface, RED,(num1*25+730, num2*25+50), 5, 0)
      else:         
        pygame.draw.circle(windowSurface, BLUE, (num1*25+730, num2*25+50), 5, 0)

 for n1 in range(0,math.floor(body_long1/10),2):#画输入层连结
    for n2 in range(0,10,2):#画输入层连结
      for m1 in range(0,math.floor(body_long2/10),2):#画隐藏层连结
       for m2 in range(0,10):
           if(tree1[(n1*10+n2)*100+m1*10+m2]>0.01):
              pygame.draw.line(windowSurface,GREEN,(n2*25+100, n1*25+50),(m2*25+400, m1*25+50),1)
              #print('tree1',tree1[(n1*10+n2)*100+m1*10+m2])
              #print('body2',body2[(m1*10+m2)])

        

 for n1 in range(0,math.floor(body_long2/10),2):#画隐藏层连结
   for n2 in range(0,10,2):
      for m1 in range(0,math.floor(body_long3/10),2):#画输出层连结
         for m2 in range(0,10):
             if(tree2[(n1*10+n2)*10+m1*10+m2]>0.01):
                pygame.draw.line(windowSurface,qing,(n2*25+400, n1*25+50),(m1*25+700, m2*25+50),1)
                #print('tree2',tree2[(n1*10+n2)*10+m1*10+m2])
                #print('body3',body3[m2])


   

        
 pygame.display.update() # 刷新一下画面，

'''


         font = pygame.font.Font("c:\simsun.ttf", 15)
         text = font.render(str(body3_std[num1*10+num2]) , True, WHITE, BLUE)
         windowSurface.blit(text, (num1*25+730, num2*25+50) ) 

'''
def normalization(lll,n):
    maximum = max(lll)
    minimum = min(lll)
    for num in range(0,n): #归一化
     lll[num]= (lll[num]-minimum)/maximum   
    return lll


        
def calculate_level2(body1,body2,body3):
         
        for num2 in range(0,body_long2): #隐藏层清零
          body2[num2]=0.001
        for num2 in range(0,body_long2):
          for num1 in range(0,body_long1):
             body2[num2]= body2[num2]+body1[num1]*tree1[num1*body_long2+num2]        
       #  body2=normalization(body2,body_long2)  ##隐藏层归一
        #print ("前2",body2) 
        for num2 in range(0,body_long2):
           body2[num2]= sigmoid(body2[num2])     #隐藏层激活函数
        #print ("后2",body2) 
        return body2

    
    
def calculate_level3(body1,body2,body3):
        for num3 in range(0,body_long3): #输出层清零
          body3[num3]=0.01
        for num3 in range(0,body_long3):#第三层计数
          for num2 in range(0,body_long2):#第二层计数
             body3[num3]= body3[num3]+body2[num2]*tree2 [num2*body_long3+num3]
        
      #   body3=normalization(body3,body_long3)   ##输出层归一
      #  print ("前3",body3) 
        for num3 in range(0,body_long3): 
           body3[num3]= sigmoid(body3[num3]) #输出层激活函数
      #  print ("后3",body3) 
        return body3




def button(n):
    global body1,body2,body3,body3_std

    body2=calculate_level2(body1,body2,body3)   
    body3=calculate_level3(body1,body2,body3)
    #print ("后3",body3) 
    dsp_csr()
    disp(n)

    return n 






    
    '''
    es = EffectScatter("动态散点图各种图形示例")
    for num1 in range(0,math.floor(body_long1/10)):#画输入层
       for num2 in range(0,10):#画输入层
           es.add("", [num1], [num2], symbol_size=10, effect_scale=0, effect_brushtype='fill', symbol="diamond")

    es.render()

    
    
    '''



def o(body1,n):
    i=0
    f = open("four.txt",encoding='utf-8')
    data=f.read()
    f.close()
    for num in data: #读取
        if(num!="\n"):
            body1[i]=int(num)
            i=i+1
    body1=normalization(body1,body_long1)
    return body1

def four(body1,n):
    i=0
    f = open("o.txt",encoding='utf-8')
    data=f.read()
    f.close()
    for num in data: #读取
        if(num!="\n"):
            body1[i]=int(num)
            i=i+1    
    body1=normalization(body1,body_long1)
    return body1



disp(n)


while True:  
  for event in pygame.event.get():
    if event.type == pygame.MOUSEBUTTONDOWN:
            mouse_pos = event.pos
            if (mouse_pos[1]>350 and mouse_pos[1]<370):
                if(mouse_pos[0]>50 and mouse_pos[0]<100):
                        body1=four(body1,n)
                        body3_std  = [0]*body_long3    #输出层标准值
                        body3_std[0]=1
                        for num3 in range(0,body_long3): 
                           body3_std[num3]= sigmoid(body3_std[num3]+0.12) #输出层激活函数
                        n=button(n)
                        
                        mouse_pos=0 
                elif(mouse_pos[0]>350 and mouse_pos[0]<400):
                        body1=o(body1,n)
                        body3_std  = [0]*body_long3    #输出层标准值
                        body3_std[4]=1
                        for num3 in range(0,body_long3): 
                           body3_std[num3]= sigmoid(body3_std[num3]+0.12) #输出层激活函数
                        n=button(n)
                        
                        mouse_pos=0 
                    
                elif(mouse_pos[0]>650 and mouse_pos[0]<750):
                    for num in range(0,n):
                       tree2=Backpropagation.tree2_cal(body2,body3,body3_std,tree2,tree_long2,body_long2,body_long3)
                       tree1=Backpropagation2.tree1_cal(body1,body2,body3,body3_std,tree1,tree_long1,tree2,tree_long2,body_long1,body_long2,body_long3)
                       body2=calculate_level2(body1,body2,body3)   
                       body3=calculate_level3(body1,body2,body3)
                    dsp_csr()
                    disp(n)
           
            
    if event.type == QUIT:  
      pygame.quit()  
      sys.exit()
      
